package com.tju.resource.business.tb_send_matl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tju.resource.common.ServiceException;
import com.tju.resource.mapper.*;
import com.tju.resource.model.*;
import com.tju.resource.result.Result;
import com.tju.resource.result.ResultEnum;
import com.tju.resource.result.ResultUtil;
import com.tju.resource.tool.tool.EmptyUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

import static com.tju.resource.tool.tool.WeightParser.parse;
import static com.tju.resource.tool.tool.WeightParser.toUnit;

/**
 *
 */
@Service
public class TbSendMatlServiceImpl extends ServiceImpl<TbSendMatlMapper, TbSendMatl>
        implements TbSendMatlService {
    @Autowired
    private TbSendMatlMapper sendMatlMapper;
    @Autowired
    private TbConsumablesMapper tbConsumablesMapper;
    @Autowired
    private TbRawMatlMapper tbRawMatlMapper;
//    @Autowired
//    private TbShipmentConsumablesMapper tbShipmentConsumablesMapper;
    @Autowired
    private TbMatlConsumablesMapper tbMatlConsumablesMapper;
    @Autowired
    private TbPpConsumablesMapper tbPpConsumablesMapper;
    @Autowired
    private TbOutwardConsumablesMapper tbOutwardConsumablesManager;
    @Autowired
    private TbPpMatlRmMapper tbPpMatlRmMapper;

    /**
     * 查询发料
     *
     * @param params
     * @return
     */
    @Override
    @Transactional
    public Result<Object> selectSendMatl(Map<String, String> params) {
        if (EmptyUtils.isNotEmpty(params.get("page")) && EmptyUtils.isNotEmpty(params.get("limit"))) {
            Page<TbSendMatl> page = new Page<>(Long.parseLong(params.get("page")), Long.parseLong(params.get("limit")));
            IPage<TbSendMatl> iPage = sendMatlMapper.selectTbSendMatl(page, params);
            List<TbSendMatl> sendMatlList = iPage.getRecords(); //发料记录

            List<String> orderNumberList = null; //订单集合
            List<String> cmdNumberList = null;//指令集合
            List<String> matlNumberList = null; //物料编号集合
            List<String> matlNameList = null;//物料名称集合

            for (TbSendMatl sendMatl : sendMatlList) {
                //物料重量单位
                String matlUnit = sendMatl.getMatlUnit();
                //原料重量单位
                String rmUnit = sendMatl.getRmUnit();
                //原料比重
                double rmFmWg = EmptyUtils.isEmpty(sendMatl.getRmFmWg()) ? 1 : sendMatl.getRmFmWg();
                //计划数
                double planNumber = EmptyUtils.isNotEmpty(sendMatl.getPlanNumber()) ? new BigDecimal(Double.toString(sendMatl.getPlanNumber())).doubleValue() : 0.0;
                //物料单重
                double  matlWeight =EmptyUtils.isNotEmpty(sendMatl.getMatlWeight())?sendMatl.getMatlWeight():0.0;
                //物料水口重
                double  wdWeight =EmptyUtils.isNotEmpty(sendMatl.getWdWeight())?sendMatl.getWdWeight():0.0;
                //物料总重=计划数*物料单重+物料水口重
                double matlTotalWeight = new BigDecimal(planNumber).doubleValue() * (matlWeight + wdWeight);
                //换算单位 物料单位 跟原料的单位换算
                double deficiencyWeight =0.0;
                //判断重量单位不为空时 是原料  //判断是0的为原料 进入计算
                if(EmptyUtils.isNotEmpty(matlUnit)&& EmptyUtils.isNotEmpty(rmUnit)&&sendMatl.getType()==0) {
                     deficiencyWeight = parse(matlTotalWeight, toUnit(matlUnit), toUnit(rmUnit));
                }
                //需要数
                long rmRadio = 0;
                //原料需要总重
                double rmTotalWeight = 0.0;
                if(EmptyUtils.isNotEmpty(sendMatl.getRmType())&&sendMatl.getType()==0){
                if(sendMatl.getRmType()==2){
                    //算出来几袋
                    rmRadio = BigDecimal.valueOf((Math.max(deficiencyWeight, 0.0)) /rmFmWg).setScale(0, RoundingMode.CEILING).longValue();
                }else if(sendMatl.getRmType()==1){
                    //换算单位 matlUnit 换算 成 rmMatl.getRmUnit()
                    rmFmWg = parse(rmFmWg, toUnit(matlUnit), toUnit(rmUnit));
                    //需要重量 =rmFmWg = 比重 * planNumber 计划数 * rmRadio 比数
                    rmTotalWeight =new BigDecimal (rmFmWg * new BigDecimal(planNumber).doubleValue() * new BigDecimal(sendMatl.getRmRadio()).doubleValue()).setScale(2,RoundingMode.CEILING).doubleValue();
                }}

                //原料需要多少袋
                sendMatl.setRmRadio(rmRadio == 0 ? null : rmRadio);
                //原料所需总重
                sendMatl.setRmTotalWeight(rmTotalWeight== 0.0?null : rmTotalWeight);
                long usageAmount;
                if (EmptyUtils.isEmpty(sendMatl.getOutConsumablesId())) {
                    //算出耗材数量
                    usageAmount = (long) (planNumber * (EmptyUtils.isNotEmpty(sendMatl.getUsageAmount()) ? sendMatl.getUsageAmount() : 0));
                } else {
                    //外发耗材数量
                    usageAmount = sendMatl.getUsageAmount();
                }
                //生产计划的耗材数
                long ppMatlNumber = 0;
                long costMatlNumber =0;
                if(sendMatl.getType()==1) {

                    if(EmptyUtils.isNotEmpty(sendMatl.getCostMatlNumber()))
                        // 物料下面的耗材数量 计划数/ 比数  计划数除以比数 向上取整 物料下面的耗材数量
                        costMatlNumber = BigDecimal.valueOf(planNumber / new BigDecimal(Double.toString(sendMatl.getCostMatlNumber())).doubleValue() / new BigDecimal(Double.toString(EmptyUtils.isEmpty(sendMatl.getMatlCount()) ? 1 : sendMatl.getMatlCount())).doubleValue()).setScale(0, RoundingMode.CEILING).longValue();
                    else if(EmptyUtils.isNotEmpty(sendMatl.getPpMatlNumber()))
                        // 上产计划下面的耗材数量 计划数/ 比数  计划数除以比数 向上取整 上产计划下面的耗材数量
                        ppMatlNumber = BigDecimal.valueOf(planNumber / new BigDecimal(Double.toString(sendMatl.getPpMatlNumber())).doubleValue() / new BigDecimal(Double.toString(EmptyUtils.isEmpty(sendMatl.getPpCount()) ? 1 : sendMatl.getPpCount())).doubleValue()).setScale(0, RoundingMode.CEILING).longValue();
                }
                int result = 0; //状态判断是外发还是出货
                if (EmptyUtils.isEmpty(sendMatl.getOrderNumber()))  //订单为空的话就是外发
                    result = 1;
                //订单不为空物料为空就是物料
                if (EmptyUtils.isNotEmpty(sendMatl.getOrderNumber()) && EmptyUtils.isEmpty(sendMatl.getMatlName()))
                    result = 2;
                if (result != 0) { //判断是这两个才进去
                    List<TbSendMatl> tbSendMatls = sendMatlMapper.selectTbSendMatlById(sendMatl.getId());  //查询出货或外发下面的的订单指令
                    orderNumberList = new ArrayList<>();//订单集合
                    cmdNumberList = new ArrayList<>();//指令集合
                    matlNumberList = new ArrayList<>();//物料编号集合
                    matlNameList = new ArrayList<>();//物料名称集合
                    for (TbSendMatl tbSendMatl : tbSendMatls) {  //循环出货,外发的订单,指令,物料编号,物料名称
                        if (EmptyUtils.isEmpty(tbSendMatl)) continue;
                        if (EmptyUtils.isNotEmpty(orderNumberList)) { //判断订单不为空
                            boolean orderNumberResult = true;//订单状态
                            for (String orderNumber : orderNumberList) {  //循环添加过的订单
                                if (orderNumber.equals(tbSendMatl.getOrderNumber())) { //如有相等就跳出循环
                                    orderNumberResult = false; //为存在
                                    break;
                                }
                            }
                            //不存在就添加
                            if (orderNumberResult) orderNumberList.add(tbSendMatl.getOrderNumber());
                        } else {
                            if (EmptyUtils.isNotEmpty(tbSendMatl.getOrderNumber()))
                                orderNumberList.add(tbSendMatl.getOrderNumber()); //第一次为空添加
                        }
                        if (EmptyUtils.isNotEmpty(cmdNumberList)) { //指令号不为空进入
                            boolean cmdNumberResult = true;//指令号状态
                            for (String cmdNumber : cmdNumberList) { //循环添加的指令号
                                if (cmdNumber.equals(tbSendMatl.getCmdNumber())) { //判断有为空的跳出循环
                                    cmdNumberResult = false; //指令号存在
                                    break;
                                }
                            }
                            //不存在添加指令号
                            if (cmdNumberResult) cmdNumberList.add(tbSendMatl.getCmdNumber());
                        } else cmdNumberList.add(tbSendMatl.getCmdNumber()); //第一次添加指令号
                        if (EmptyUtils.isNotEmpty(matlNumberList)) {//判断物料编号不为空就进入
                            boolean matlNumberResult = true;//物料编号状态
                            for (String matlNumber : matlNumberList) {//循环添加的物料编号
                                if (matlNumber.equals(tbSendMatl.getMatlNumber())) {//判断物料编号存在就跳出
                                    matlNumberResult = false; //为存在状态
                                    break;
                                }
                            }
                            //不存在就添加物料编码
                            if (matlNumberResult) matlNumberList.add(tbSendMatl.getMatlNumber());
                        } else matlNumberList.add(tbSendMatl.getMatlNumber()); //第一次添加物料编号
                        if (EmptyUtils.isNotEmpty(matlNameList)) { //不为空就进入循环
                            boolean matlNameResult = true;//物料名称状态
                            for (String matlName : matlNameList) { //循环添加的物料名称
                                if (matlName.equals(tbSendMatl.getMatlName())) {//判断存在就跳出循环
                                    matlNameResult = false;//为存在状态
                                    break;
                                }
                            }
                            //不存在就添加物料名称
                            if (matlNameResult) matlNameList.add(tbSendMatl.getMatlName());
                        } else matlNameList.add(tbSendMatl.getMatlName()); //第一次添加物料名称
                    }
                }
                String matlNumber = matlNumberList + "";
                String matlName = matlNameList + "";
                if (result == 1) {
                    String orderNumber = orderNumberList + "";
                    //把他们的括号取消
                    sendMatl.setOrderNumber(orderNumber.replace("]", "").replace("[", ""));
                    String cmdNumber = cmdNumberList + "";
                    sendMatl.setCmdNumber(cmdNumber.replace("]", "").replace("[", ""));
                    sendMatl.setMatlNumber(matlNumber.replace("]", "").replace("[", ""));
                    sendMatl.setMatlName(matlName.replace("]", "").replace("[", ""));
                } else if (result == 2) {
                    sendMatl.setMatlNumber(matlNumber.replace("]", "").replace("[", ""));
                    sendMatl.setMatlName(matlName.replace("]", "").replace("[", ""));
                }
                //耗材数量
                long costNumber = costMatlNumber != 0 ? costMatlNumber : EmptyUtils.isNotEmpty(sendMatl.getShipmentMaterialNumber()) ? sendMatl.getShipmentMaterialNumber() : usageAmount != 0 ? usageAmount : ppMatlNumber;
                sendMatl.setCostMatlNumber(costNumber == 0 ? null : costNumber);
            }
            return ResultUtil.success(ResultEnum.SUCCESS, sendMatlList, sendMatlList.size());
        }
        return ResultUtil.error(ResultEnum.UNKONW_ERROR, "缺少参数!");

    }

    /**
     * 审核发料
     *
     * @param sendMatl
     * @return
     */
    @Override
    @Transactional
    public Result<Object> approveSendMatl(TbSendMatl sendMatl) {
        if (EmptyUtils.isNotEmpty(sendMatl.getId())) {
            TbSendMatl tbSendMatl = sendMatlMapper.selectById(sendMatl.getId());
            if (EmptyUtils.isEmpty(tbSendMatl)) return ResultUtil.error(ResultEnum.UNKONW_ERROR, "不存在发料!");
            if (sendMatl.getType() == 1) {
                Long consumablesId = sendMatl.getConsumablesId();//耗材id
                Long costMatlNumber = sendMatl.getCostMatlNumber();//耗材数量
                TbConsumables tbConsumables = tbConsumablesMapper.selectById(consumablesId); //查询耗材
                if (EmptyUtils.isNotEmpty(tbConsumables)) {  //判断耗材不为空
                    if (EmptyUtils.isEmpty(costMatlNumber))
                        return ResultUtil.error(ResultEnum.UNKONW_ERROR, "耗材数量不能为空!");
                    //减去数量
                    if (tbConsumables.getNumber() < costMatlNumber)
                        return ResultUtil.error(ResultEnum.UNKONW_ERROR, "耗材库存不足需要采购!");
                    tbConsumables.setNumber((int) (tbConsumables.getNumber() - costMatlNumber < 0 ? 0 : tbConsumables.getNumber() - costMatlNumber));
                    //大于0
                    if (tbConsumablesMapper.updateById(tbConsumables) == 0)
                        throw new ServiceException("耗材数量修改失败!");
                    // 第一个出货跟耗材的关联id  第二个生产计划跟耗材的关联id   第三个外发跟耗材的关联id
                    //if ((EmptyUtils.isNotEmpty(sendMatl.getPpConsumablesId()) ? updateWrapper(tbPpConsumablesMapper, sendMatl.getPpConsumablesId()) : EmptyUtils.isNotEmpty(sendMatl.getOutConsumablesId()) ? updateWrapper(tbOutwardConsumablesManager, sendMatl.getOutConsumablesId()) : 0) == 0)
                    if ((EmptyUtils.isNotEmpty(sendMatl.getMatlConsumablesId()) ? updateWrapper(tbMatlConsumablesMapper, sendMatl.getMatlConsumablesId()) : EmptyUtils.isNotEmpty(sendMatl.getPpConsumablesId()) ? updateWrapper(tbPpConsumablesMapper, sendMatl.getPpConsumablesId()) : EmptyUtils.isNotEmpty(sendMatl.getOutConsumablesId()) ? updateWrapper(tbOutwardConsumablesManager, sendMatl.getOutConsumablesId()) : 0) == 0)
                        throw new ServiceException("发料状态修改失败!");
                } else {
                    return ResultUtil.error(ResultEnum.UNKONW_ERROR, "耗材不存在!");
                }
            } else {
                Long rmId = sendMatl.getRmId();//原材料id

                TbRawMatl tbRawMatl = tbRawMatlMapper.selectById(rmId);//查询原材料
                if (EmptyUtils.isNotEmpty(tbRawMatl)) {
                    if(tbRawMatl.getRmType()==2) {
                        Long rmRadio = sendMatl.getRmRadio();//原材料数量
                        if (EmptyUtils.isEmpty(rmRadio))
                            return ResultUtil.error(ResultEnum.UNKONW_ERROR, "原料数量不能为空!");
                        //减去数量
                        if (tbRawMatl.getRmStoke() < rmRadio)
                            throw new ServiceException("原材料库存不足需要采购!");
                        tbRawMatl.setRmStoke((int) (tbRawMatl.getRmStoke() - rmRadio < 0 ? 0 : tbRawMatl.getRmStoke() - rmRadio));
                    }else if(tbRawMatl.getRmType()==1){
                        double rmTotalWeight = sendMatl.getRmTotalWeight();//原料重量
                        if (EmptyUtils.isEmpty(rmTotalWeight))
                            return ResultUtil.error(ResultEnum.UNKONW_ERROR, "原料数量不能为空!");
                        //减去数量
                        if (tbRawMatl.getRmStoke() < rmTotalWeight)
                            throw new ServiceException("原材料库存不足需要采购!");
                        tbRawMatl.setRmStoke((tbRawMatl.getRmStoke() - rmTotalWeight < 0 ? 0 : tbRawMatl.getRmStoke() - rmTotalWeight));
                    }
                    //大于0
                    if (tbRawMatlMapper.updateById(tbRawMatl) == 0)
                        throw new ServiceException("原材料数量修改失败!");
                    //生产计划跟物料跟原材料的关联id

                    if ((EmptyUtils.isNotEmpty(sendMatl.getPpMaliRmId()) ? updateWrapper(tbPpMatlRmMapper, sendMatl.getPpMaliRmId()) : 0) == 0)
                        throw new ServiceException("发料状态修改失败!");
                } else {
                    return ResultUtil.error(ResultEnum.UNKONW_ERROR, "原材料不存在!");
                }
            }
            tbSendMatl.setApproveBy(sendMatl.getApproveBy());//审核人
            tbSendMatl.setApproveStatus(1);
            tbSendMatl.setApproveTime(new Date());
            if (sendMatlMapper.updateById(tbSendMatl) > 0) {//修改
                return ResultUtil.success(ResultEnum.SUCCESS, "发料成功!");
            }
            throw new ServiceException("发料失败!");
        }
        return ResultUtil.error(ResultEnum.UNKONW_ERROR, "发料失败!");
    }

    /**
     * 判断该生产计划下面的发料是否全审核过
     *
     * @param id
     * @return
     */
    @Override
    public boolean approvePlan(Long id) {
        TbSendMatl sendMatl = sendMatlMapper.selectTbSendMatlByPPId(id);
        return EmptyUtils.isNotEmpty(sendMatl) && (EmptyUtils.isEmpty(sendMatl.getApproveStatus()));
    }

    /**
     * 修改发料状态
     */
    public <T> int updateWrapper(BaseMapper<T> mapper, Long id) {
        UpdateWrapper<T> upd = new UpdateWrapper<>();
        upd.set("issuing_status", 1);
        upd.eq("id", id);
        return mapper.update(null, upd);
    }
}




